package com.changanw.dynamic.thread.pool.sdk.domain;

import com.alibaba.fastjson.JSON;
import com.changanw.dynamic.thread.pool.sdk.domain.model.ThreadPoolConfigEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author changanw
 * @description 动态线程池服务
 * @date 2024/5/15 11:14
 */
public class DynamicThreadPoolService implements IDynamicThreadPoolService{
  private final Logger logger = LoggerFactory.getLogger(DynamicThreadPoolService.class);

  private final String applicationName;
  private final Map<String, ThreadPoolExecutor> threadPoolExecutorMap;
  @Resource
  private ApplicationContext context;

  public DynamicThreadPoolService(String applicationName, Map<String, ThreadPoolExecutor> threadPoolExecutorMap) {
    this.applicationName = applicationName;
    this.threadPoolExecutorMap = threadPoolExecutorMap;
  }
  @Override
  public List<ThreadPoolConfigEntity> queryThreadPoolList() {
    Set<String> threadPoolBeanNames = threadPoolExecutorMap.keySet();
    List<ThreadPoolConfigEntity> threadPoolVOS = new ArrayList<>(threadPoolBeanNames.size());
    for (String beanName : threadPoolBeanNames) {
      ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(beanName);
      ThreadPoolConfigEntity threadPoolConfigVO = new ThreadPoolConfigEntity(applicationName, beanName);
      threadPoolConfigVO.setCorePoolSize(threadPoolExecutor.getCorePoolSize());
      threadPoolConfigVO.setMaximumPoolSize(threadPoolExecutor.getMaximumPoolSize());
      threadPoolConfigVO.setActiveCount(threadPoolExecutor.getActiveCount());
      threadPoolConfigVO.setPoolSize(threadPoolExecutor.getPoolSize());
      threadPoolConfigVO.setQueueType(threadPoolExecutor.getQueue().getClass().getSimpleName());
      threadPoolConfigVO.setQueueSize(threadPoolExecutor.getQueue().size());
      threadPoolConfigVO.setRemainingCapacity(threadPoolExecutor.getQueue().remainingCapacity());
      threadPoolVOS.add(threadPoolConfigVO);
    }
    return threadPoolVOS;
  }

  @Override
  public ThreadPoolConfigEntity queryThreadPoolConfigByName(String threadPoolName) {
    ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(threadPoolName);
    if (null == threadPoolExecutor) return new ThreadPoolConfigEntity(applicationName, threadPoolName);

    // 线程池配置数据
    ThreadPoolConfigEntity threadPoolConfigVO = new ThreadPoolConfigEntity(applicationName, threadPoolName);
    threadPoolConfigVO.setCorePoolSize(threadPoolExecutor.getCorePoolSize());
    threadPoolConfigVO.setMaximumPoolSize(threadPoolExecutor.getMaximumPoolSize());
    threadPoolConfigVO.setActiveCount(threadPoolExecutor.getActiveCount());
    threadPoolConfigVO.setPoolSize(threadPoolExecutor.getPoolSize());
    threadPoolConfigVO.setQueueType(threadPoolExecutor.getQueue().getClass().getSimpleName());
    threadPoolConfigVO.setQueueSize(threadPoolExecutor.getQueue().size());
    threadPoolConfigVO.setRemainingCapacity(threadPoolExecutor.getQueue().remainingCapacity());

    if (logger.isDebugEnabled()) {
      logger.info("动态线程池，配置查询 应用名:{} 线程名:{} 池化配置:{}", applicationName, threadPoolName, JSON.toJSONString(threadPoolConfigVO));
    }

    return threadPoolConfigVO;
  }

  @Override
  public void updateThreadPoolConfig(ThreadPoolConfigEntity threadPoolConfigEntity) {
    if (null == threadPoolConfigEntity || !applicationName.equals(threadPoolConfigEntity.getAppName())) return;
    ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorMap.get(threadPoolConfigEntity.getThreadPoolName());
    //如果发布的线程池名称在redis中不存在，就新建一个
    if (null == threadPoolExecutor){
      //新创建一个线程池配置
      threadPoolExecutor = new ThreadPoolExecutor(threadPoolConfigEntity.getCorePoolSize(),
              threadPoolConfigEntity.getMaximumPoolSize(),
              Long.valueOf(context.getEnvironment().getProperty("thread.pool.executor.config.keep-alive-time")),
              TimeUnit.SECONDS,
              new LinkedBlockingQueue<>(Integer.parseInt(context.getEnvironment().getProperty("thread.pool.executor.config.block-queue-size"))),
              Executors.defaultThreadFactory(),
              new ThreadPoolExecutor.AbortPolicy());
      threadPoolExecutorMap.put(threadPoolConfigEntity.getThreadPoolName(),threadPoolExecutor);
    }

    // 设置参数 「调整核心线程数和最大线程数」
    threadPoolExecutor.setCorePoolSize(threadPoolConfigEntity.getCorePoolSize());
    threadPoolExecutor.setMaximumPoolSize(threadPoolConfigEntity.getMaximumPoolSize());
  }
}
